home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
fish
/
701-725
/
704
/
sunclock
/
src.lha
/
Sun.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-04
|
6KB
|
242 lines
/*-------------------------------------------------------------------------
SunClock
Amiga version by Mark Waggoner,
waggoner@ichips.intel.com or wagnell@PDaXcess.techbook.com
December 1991
Sun.c
Routines to calculate and set the illumination mask for the sun clock
-------------------------------------------------------------------------*/
#include <time.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <functions.h>
#include <string.h>
#include <graphics/gfx.h>
#include "sunmath.h"
extern struct BitMap MapBitMap,IllumBitMap;
extern UWORD DataWidth,DataHeight;
extern WORD *Illum;
extern void (*MapRefresh)(void);
extern void (*TextRefresh)(void);
extern char loctimestr[],gmtimestr[];
/*-------------------------------------------------------------------------
Draw a horizontal line segment into the bitmap data
x0 must be less than x1 and both must be > 0
-------------------------------------------------------------------------*/
Segment(UBYTE *line,int x0,int x1)
{
UBYTE *sp,*ep,sm,em;
sp = line + x0/8;
ep = line + x1/8;
sm = 0xff>>(x0%8);
em = 0xff<<(7-x1%8);
if (sp == ep) {
*sp = (sm & em);
return;
}
*sp |= sm;
while (++sp<ep) *sp = 0xff;
*ep |= em;
}
/*-------------------------------------------------------------------------
Set the illumination mask bitmap.
y is the row to set,
noon is the midpoint of the mask
width is half the width of the mask
-------------------------------------------------------------------------*/
void
SetIllum(int noon,int y,int width)
{
UBYTE *line;
int x0,x1;
if (width == 0) width = 1;
if (width < 0) return;
if (y >= DataHeight) return;
line = (UBYTE *)IllumBitMap.Planes[0] + (y * ((DataWidth + 15) / 16) * 2);
x0 = noon - width;
x1 = noon + width;
if (x0<0) {
Segment(line,DataWidth+(x0%DataWidth),DataWidth-1);
x0 = 0;
}
if (x1 >= DataWidth) {
Segment(line,0,x1%DataWidth);
x1 = DataWidth-1;
}
Segment(line,x0,x1);
}
/*-------------------------------------------------------------------------
Project the suns illumination onto the bitmap mask
-------------------------------------------------------------------------*/
#define tableval(i,v) if (i>=0 && i<DataHeight) { Illum[i] = ((v)==0) ? 1 : (v); }
static void
ProjectIllumination(int noon,double dec)
{
int i,j, ftf = 1;
int ilon, ilat, lilon, lilat, xt;
double m, x, y, z, th, lon, lat, s, c;
for(i=0;i<DataHeight;i++)
Illum[i] = -1;
/* Build transformation for declination */
dec = dtr(dec);
s = sin(-dec);
c = cos(-dec);
/* Increment over a semicircle of illumination */
for (th = -(PI / 2); th <= PI / 2 + 0.001; th += PI / TERMINC) {
/* Transform the point through the declination rotation. */
x = -s * sin(th);
y = cos(th);
z = c * sin(th);
/* Transform the resulting co-ordinate through the
map projection to obtain screen co-ordinates. */
lon = (y == 0 && x == 0) ? 0.0 : rtd(atan2(y, x));
lat = rtd(asin(z));
ilat = DataHeight - (lat + 90) * (DataHeight / 180.0);
ilon = lon * (DataWidth / 360.0);
if (ftf) { /* First time. Just save start co-ordinate. */
lilon = ilon;
lilat = ilat;
ftf = 0;
} else {
if (lilat == ilat) { /* Set width */
j = (DataHeight - 1) - ilat;
tableval(j,ilon);
} else { /* interpolate intermediate points */
m = ((double) (ilon - lilon)) / (ilat - lilat);
for (i = lilat; i != ilat; i += sgn(ilat - lilat)) {
xt = lilon + floor((m * (i - lilat)) + 0.5);
j = (DataHeight - 1) - i;
tableval(j,xt);
}
}
lilon = ilon;
lilat = ilat;
}
}
/* Now tweak the widths to generate full illumination for
the correct pole. */
if (dec < 0.0) {
ilat = DataHeight - 1;
lilat = -1;
} else {
ilat = 0;
lilat = 1;
}
for (i = ilat; i != DataHeight / 2; i += lilat) {
if (Illum[i] != -1) {
while (1) {
tableval(i,DataWidth/2);
if (i == ilat)
break;
i -= lilat;
}
break;
}
}
for(i=0;i<DataHeight;i++)
SetIllum(noon,i,Illum[i]);
}
/*-------------------------------------------------------------------------
Update the illumination if it has been long enough since the
last update.
-------------------------------------------------------------------------*/
void
UpdateImages(int force)
{
time_t timeval;
static time_t lasttime = 0;
struct tm lt,*ct;
double jt,gt;
double sunra,sundec,sunrv,sunlong;
double lastdec;
double a;
int xl;
static int lastxl = -1;
LONG sec0,mic0,sec1,mic1;
char *tz;
/* Find out what time it is */
time(&timeval);
lt = *localtime(&timeval);
ct = gmtime(&timeval);
if (!ct) ct = <
jt = jtime(ct);
if (tz = getenv("TZ")) {
strncpy(loctimestr,tz,3);
loctimestr[3] = ':';
loctimestr[4] = ' ';
loctimestr[5] = '\0';
strcat(loctimestr,asctime(<));
loctimestr[strlen(loctimestr)-1] = '\0';
}
else
strcpy(loctimestr,"TZ Environment variable not set!");
strcpy(gmtimestr,"GMT: ");
strcat(gmtimestr,asctime(ct));
gmtimestr[strlen(gmtimestr)-1] = '\0';
TextRefresh();
if ((timeval > lasttime) && ((timeval - lasttime) < 60) && !force) return;
lasttime = timeval;
sunpos(jt, 0, &sunra, &sundec, &sunrv, &sunlong);
gt = gmst(jt);
/* printf("RA: %g DEC: %g RV: %g LONG: %g\n",sunra,sundec,sunrv,sunlong); */
a = 180.0 + (sunra - (gt * 15));
sunlong = fixangle(a);
xl = sunlong * ((double) DataWidth / 360.0);
/* If the subsolar point has moved at least one pixel, update
the illuminated area on the screen. */
if ((lastxl != xl) || (fabs(sundec - lastdec) > 5) || force) {
BltClear((char *)IllumBitMap.Planes[0],
((DataWidth+15)/16)*2*DataHeight,1);
ProjectIllumination(xl,sundec);
BltBitMap(&MapBitMap,0,0,&IllumBitMap,0,0,
DataWidth,DataHeight,0x60,0x01,0);
(*MapRefresh)();
lastxl = xl;
lastdec = sundec;
}
}